from PIL import Image


def median_filter_rgb(image_path, output_path, kernel_size):
    """
    对输入的RGB图像进行中值滤波处理。

    参数:
    image_path (str): 输入图像的文件路径。
    output_path (str): 输出滤波后图像的文件路径。
    kernel_size (int): 滤波核的大小，通常为奇数，如3、5等，表示滤波核是kernel_size * kernel_size的正方形。
    """
    # 打开原始图像
    image = Image.open(image_path)
    # 获取图像的宽度和高度
    width, height = image.size
    # 计算滤波核半径（用于后续遍历像素点周边范围）
    radius = kernel_size // 2
    # 创建新的空白图像，尺寸与原图像相同，模式也相同
    new_image = Image.new(image.mode, (width, height))
    # 遍历图像的每个像素点（避开边缘部分，边缘可后续单独处理或者忽略）
    for y in range(radius, height - radius):
        for x in range(radius, width - radius):
            # 分别用于存储红、绿、蓝通道滤波核覆盖像素点的像素值列表
            red_pixel_values = []
            green_pixel_values = []
            blue_pixel_values = []
            # 遍历滤波核范围内的像素点
            for ky in range(y - radius, radius + y):
                for kx in range(x - radius, radius + x):
                    # 获取原图像中对应坐标的像素
                    pixel = image.getpixel((kx, ky))
                    red, green, blue = pixel
                    red_pixel_values.append(red)
                    green_pixel_values.append(green)
                    blue_pixel_values.append(blue)
            # 对各通道的像素值列表进行排序
            sorted_red_pixel_values = sorted(red_pixel_values)
            sorted_green_pixel_values = sorted(green_pixel_values)
            sorted_blue_pixel_values = sorted(blue_pixel_values)
            # 取各通道的中值
            median_red = sorted_red_pixel_values[len(sorted_red_pixel_values) // 2]
            median_green = sorted_green_pixel_values[len(sorted_green_pixel_values) // 2]
            median_blue = sorted_blue_pixel_values[len(sorted_blue_pixel_values) // 2]
            # 将中值设置到新图像对应的坐标位置
            new_image.putpixel((x, y), (median_red, median_green, median_blue))
    # 保存滤波后的图像
    new_image.save(output_path)
    return new_image


image_path = "D:/cangku/computer-image-project-design/test.jpg"
output_path = "D:/cangku/computer-image-project-design/test1.jpg"
kernel_size = 3
median_filter_rgb(image_path, output_path, kernel_size)